package com.lc.common.handler;

import com.lc.common.bean.response.Result;
import com.lc.common.exception.HandlerException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;

/**
 * 全局异常处理
 * <p>
 * 参数校验拦截器
 *
 * @author lingchou
 */
@RestControllerAdvice
public class GlobalExceptionHandler {

    /**
     * 参数校验异常拦截 POST方式
     *
     * @param m 异常 {@link MethodArgumentNotValidException}
     * @return 返回参数错误的信息
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Result<String> myMethodArgumentNotValid(MethodArgumentNotValidException m) {
        String message = m.getBindingResult().getFieldErrors().stream().map(FieldError::getDefaultMessage).collect(Collectors.joining(","));
        return Result.paramFailure(message);
    }

    /**
     * 参数校验异常拦截 GET方式
     *
     * @param c 异常 {@link ConstraintViolationException}
     * @return 返回参数错误的信息
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public Result<String> constraintViolationException(ConstraintViolationException c) {
        String message = c.getConstraintViolations().stream().map(cv -> cv == null ? "null" : cv.getMessage()
        ).collect(Collectors.joining(", "));
        return Result.paramFailure(message);
    }

    /**
     * 参数校验 字段必传，针对 @RequestParam 中默认required为true 的时候触发参数不存在，返回500的情况
     *
     * @param m 异常 {@link MissingServletRequestParameterException}
     * @return 必须的字段 {参数名称}，字段类型 {参数类型}，不能为空
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public Result<String> missingServletRequestParameterException(MissingServletRequestParameterException m) {
        String message = String.format("必须的字段 %s，字段类型 %s，不能为空", m.getParameterName(), m.getParameterType());
        return Result.paramFailure(message);
    }

    /**
     * 拦截Handler异常
     *
     * @param e 异常 {@link HandlerException}
     * @return 返回错误
     */
    @ExceptionHandler(HandlerException.class)
    public Result<String> handlerException(HandlerException e) {
        return Result.failure(e.getMessage());
    }
}
